﻿using EssentialWebFramework.Models.LogModels;
using EssentialWebFramework.Utils;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Web;

namespace EssentialWebFramework.Common.Middlewares
{
    /// <summary>
    /// 访问记录日志 中间件
    /// </summary>
    public class AccessLogMiddleware
    {
        /// <summary>
        /// next
        /// </summary>
        private RequestDelegate _next;

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="next"></param>
        public AccessLogMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        /// <summary>
        /// Invoke
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            // 获取请求中的 日志 服务组件
            ILogger<AccessLogMiddleware> logger = context.RequestServices.GetService<ILogger<AccessLogMiddleware>>();

            if (context.WebSockets.IsWebSocketRequest)
            {
                await _next(context);
            }
            else
            {
                string queryString = HttpUtility.UrlDecode(context.Request.QueryString.Value);  // 查询
                string requsetContent = GetRequestContent(context); // 请求内容

                await _next(context);

                // 记录日志
                LogAccess logAccess = new LogAccess()
                {
                    Path = context.Request.Path + (string.IsNullOrEmpty(queryString) ? string.Empty : queryString),
                    RequestParams = requsetContent,
                    UserId = context.User.Identity.Name,
                    ResultCode = context.Response.StatusCode.ToString(),
                    CreateTime = DateTime.Now
                };
                logger.LogDebug(JsonUtils.JsonSerializeForFront(logAccess));
            }            
        }

        /// <summary>
        /// 获取请求内容
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        private static string GetRequestContent(HttpContext httpContext)
        {
            string requestBodyStr = string.Empty;
            Stream requestBodyStream = httpContext.Request.Body;

            if (requestBodyStream.CanSeek)
            {
                requestBodyStream.Seek(0, SeekOrigin.Begin);    // 需要相应中间件的支持，否则 Request.Body 无法 seek
                StreamReader sr = new StreamReader(requestBodyStream);
                requestBodyStr = sr.ReadToEndAsync().Result;
                requestBodyStream.Seek(0, SeekOrigin.Begin);
            }
            else if (httpContext.Request.HasFormContentType)
            {
                requestBodyStr = string.Join("&", httpContext.Request.Form.Keys.Select(key => $"{ key }={httpContext.Request.Form[key]}"));

                if(httpContext.Request.Form.Files.Count > 0)
                {
                    requestBodyStr += $"，并包含 { httpContext.Request.Form.Files.Count } 个文件" +
                                        $"（{ string.Join("\t", httpContext.Request.Form.Files.Select(a => $"{ a.FileName }-{ a.Length / 1000.0} KB")) }）";
                }
            }

            return requestBodyStr;
        }
    }
}
